#include "ramka.hpp"
//#include "Wyjatki.hpp"
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <boost/crc.hpp>  // for boost::crc_32_type



using namespace std;

Ramka::Ramka() {

}

TematKomunikacji Ramka::pobierzTemat() const {
   return temat;
}

string Ramka::pobierzDane() const {
   return dane;
}

string Ramka::pobierzLogin() const {
   if(temat == logowanieTCP) {
      return login;
   } else {
      //throw
   }
}

string Ramka::pobierzHaslo() const {
   if(temat == logowanieTCP) {
      return haslo;
   } else {
      //throw
   }

}

int Ramka::pobierzOdKogo() const {
   return odKogo;
}

void Ramka::ustawOdKogo(int odKogo) {
   this->odKogo = odKogo;
}


void Ramka::sprawdzRamkeOdebrana(string ramka) {
   size_t pos;
   boost::crc_32_type  tempCRC;
   string stringCRC;
   string test = ramka;
   
   if ( ((pos = ramka.find_first_of(">")) != string::npos) && (pos == 0) ) {
      ramka.erase(ramka.begin());
   } else {
      //throw Wyjatek("Bledna ramka (brakuje >)");
   }


   if ( ((pos = ramka.find_first_of("<")) != string::npos) && (pos == ramka.size() - 1) ) {
      ramka.erase(ramka.begin() + pos);
   } else {
      //throw Wyjatek("Bledna ramka (brakuje <)");
   }

    
   // szukam rozpoczecia CRC w ramce i je wycinam

   if ( (pos  = ramka.rfind("/")) != string::npos ) {
      stringCRC = ramka.substr(pos + 1);
      ramka.erase(pos);
      if ( !(stringCRC.size()) ) {
	 //throw Wyjatek("Bledna ramka (brak CRC)");
      }
   }
   else {
      //throw Wyjatek("Bledna ramka (brakuje drugiego /)");
   }

   tempCRC.process_block(ramka.c_str(), ramka.c_str() + ramka.size());

   // sprawdzam CRC pobrane i policzone
   if ( tempCRC.checksum() != boost::lexical_cast<boost::uint32_t>(stringCRC)) {
      //throw Wyjatek("Bledna ramka (niezgodne CRC)");
   }


   // wycinam temat wiadomosci i dane wiadomosci (jesli jakies sa)
   if ( (pos  = ramka.find("/")) != string::npos ) {
      temat = static_cast<TematKomunikacji>(boost::lexical_cast<int>(ramka.substr(0, pos)));
      dane = ramka.substr(pos + 1);
   }
   else {
      //throw Wyjatek("Bledna ramka (brakuje pierwszego |)");
   }


   if(temat == logowanieTCP) {
      login = pobierzLoginZDanych();
      haslo = pobierzHasloZDanych();
   }
}

/*static*/
string Ramka::stworzRamkeDoWyslania(enum TematKomunikacji temat,
				    string wiadomosc) {
   
   boost::crc_32_type CRC;
   string wynik(boost::lexical_cast<string>(temat) + "/" + wiadomosc);
   //wynik.append("/");
   //wynik.append(wiadomosc);
   CRC.process_block(wynik.c_str(), wynik.c_str() + wynik.size());
   wynik = ">" + wynik + "/" + boost::lexical_cast<string>(CRC.checksum()) + "<";
   //string wynikCRC(">" + wynik + "/" + boost::lexical_cast<string>(CRC.checksum()) + "<");
   
   return wynik;
}

/*static*/
string Ramka::zamienMapeCLINaString(cliext::map<System::String^,int> mapa) {
   string wynik;
   cliext::map<System::String^,int>::const_iterator it = mapa.begin();
   
   for(; it != mapa.end(); ++it) {
	  const int second = it->second;
      wynik.append(Ramka::ToStdString(it->first) + ":" +
		   boost::lexical_cast<string>(second) + ";");
   }
   return wynik;
}

/*static*/
string Ramka::zamienWektorCLINaString(cliext::vector<System::String^> wektor) {
   string wynik;
   cliext::vector<System::String^>::const_iterator it = wektor.begin();
   
   for(; it != wektor.end(); ++it) {
      wynik.append(Ramka::ToStdString(*it) + ";");
   }
   return wynik;
}


/*static*/
cliext::map<System::String^,int> Ramka::zamienStringNaMapeCLI(string dane) {
   cliext::map<System::String^,int> wynik;
   System::String^ daneSys = Ramka::ToSysString(dane);
   int found;
   System::String^ first;
   int second;
   while(!System::String::IsNullOrEmpty(daneSys)) {
      if((found = daneSys->IndexOf(":")) > 0) {

	 first = daneSys->Substring(0, found);
	 daneSys = daneSys->Substring(found + 1);
      } else {

      }
      if((found = daneSys->IndexOf(";")) > 0) {	 
	 // parse integer
	 second = System::Int32::Parse(daneSys->Substring(0, found));
	 daneSys = daneSys->Substring(found + 1);
      } else {
	   
      }

      wynik[first] = second;
   }
   return wynik;   
}

string Ramka::zamienMapeNaString(map<string,string> mapa) {
   string wynik;
   map<string,string>::const_iterator it = mapa.begin();   
   for(; it != mapa.end(); ++it) {
      wynik.append(it->first + ":" + it->second + ";");
   }
   return wynik;
}

map<string,string> Ramka::zamienStringNaMape(string dane) {
    size_t found;
    string first, second;
    map<string,string> wynik;

    while(dane.size()) {
        if( (found = dane.find(":")) != string::npos ) {
	   first = dane.substr(0, found);
	   dane.erase(0, found + 1);
        } else {

        }
        if( (found = dane.find(";")) != string::npos ) {
	   second = dane.substr(0, found);
	   dane.erase(0, found + 1);
        } else {

        }
        wynik[first] = second;
    }
    return wynik;  
}

cliext::vector<System::String^> Ramka::zamienStringNaWektorCLI(string dane) {
   cliext::vector<System::String^> wynik;
   System::String^ daneSys = Ramka::ToSysString(dane);
   int found;
   System::String^ first;
   int second;
   while(!System::String::IsNullOrEmpty(daneSys)) {
      if((found = daneSys->IndexOf(";")) > 0) {

	 first = daneSys->Substring(0, found);
	 daneSys = daneSys->Substring(found + 1);
      } else {

      }
      wynik.push_back(first);
   }
   return wynik; 
}

string Ramka::zamienWektorDoubleNaString(cliext::vector<double> wektor) {
   string wynik;
   cliext::vector<double>::iterator it = wektor.begin();
   
   for(; it != wektor.end(); ++it) {
	   double temp = *it;
      wynik.append(boost::lexical_cast<std::string>(temp) + ";");
   }
   return wynik;
}

cliext::vector<double> Ramka::zamienStringNaWektorDouble(string dane) {
   cliext::vector<double> wynik;
   System::String^ daneSys = Ramka::ToSysString(dane);
   int found;
   double first;
   while(!System::String::IsNullOrEmpty(daneSys)) {
      if((found = daneSys->IndexOf(";")) > 0) {
	 first = System::Double::Parse(daneSys->Substring(0, found));
	 daneSys = daneSys->Substring(found + 1);
      } else {

      }
      wynik.push_back(first);
   }
   return wynik; 
}

string Ramka::pobierzLoginZDanych() {
   size_t found;
   if( (found = dane.find("#")) != string::npos) {
      return dane.substr(0, found);
   } else {
      //throw Wyjatek("Brak znaku #, wiec nie moge znalezc loginu");
   }
}

string Ramka::pobierzHasloZDanych() {
   size_t found;
   if( (found = dane.find("#")) != string::npos) {
      return dane.substr(found + 1, string::npos);
   } else {
      //throw Wyjatek("Brak znaku #, wiec nie moge znalezc hasla");
   }
}



Ramka::~Ramka() {

}
